<template>
  <el-upload
    v-loading="loading"
    class="uploader"
    element-loading-text="正在上传..."
    accept="image/*"
    :action="QINIU_UPLOAD_URL"
    :class="{'hover-mask': modelValue}"
    :show-file-list="false"
    :data="param"
    :on-error="handleError"
    :on-success="handleSuccess"
    :before-upload="beforeUpload"
  >
    <el-image v-if="modelValue" class="image" :src="modelValue" fit="cover" />
    <i class="el-icon-plus uploader-icon"></i>
  </el-upload>
</template>

<script setup>
import {ref} from 'vue'
import {ElMessage} from 'element-plus'
import {isImage} from '@/function/regular'
import {getQiniuToken} from '@/service/upload'
import {getRandomStr} from '@/utils/tools'
import {QINIU_UPLOAD_URL, QINIU_PREFIX} from '@/utils/constant'

// eslint-disable-next-line
const emits = defineEmits(['input'])
// eslint-disable-next-line
defineProps({
  modelValue: String
})

const loading = ref(false)
const param = ref({
  token: '',
  key: ''
})

function handleSuccess(res) {
  loading.value = false
  const {key} = res
  const imageUrl = QINIU_PREFIX + key
  emits('input', imageUrl)
}
function handleError(err) {
  console.log(err)
  loading.value = false
  ElMessage.close()
  ElMessage.error('上传失败!')
}
function beforeUpload(file) {
  if (!isImage(file.type)) {
    ElMessage.error('只能上传 JPG、PNG、GIF 格式!')
    return false
  }

  return new Promise((resolve, reject) => {
    loading.value = true
    getQiniuToken()
      .then(res => {
        const {token} = res
        param.value = {
          token,
          key: getRandomStr() + file.name
        }
        resolve()
      })
      .catch(err => {
        console.log(err)
        loading.value = false
        ElMessage.closel()
        ElMessage.error('上传失败!')
        reject(err)
      })
  })
}
</script>

<style scoped lang="scss">
.uploader {
  @include wh(130px, 130px);
  border: 1px dashed #d9d9d9;
  @include borderRadius(6px);
  cursor: pointer;
  &:hover {
    border-color: #409eff;
  }
  :deep(.el-upload)  {
    position: relative;
    @include wh(100%, 100%);
    overflow: hidden;
  }
}
.uploader-icon {
  position: absolute;
  top: 0;
  left: 0;
  @include wh(100%, 100%);
  line-height: 128px;
  text-align: center;
  font-size: 28px;
  color: #8c939d;
}
.image + .uploader-icon {
  opacity: 0;
}
.image {
  @include wh(128px, 128px);
  @include borderRadius(6px);
  display: block;
}
.hover-mask:hover .uploader-icon {
  opacity: 1;
  background-color: rgba(0, 0, 0, 0.2);
  color: $color-text;
}
</style>

